//
// Created by pzw on 24-2-22.
//

#include "file_stdio.h"

/**
 * fopen类似底层的open系统调用；它主要用于文件和终端的输入和输出；
 * 如果你需要对设备进行明确的控制，那最好使用底层系统调用，因为这可以避免使用库函数带来的一些潜在问题；
 * 如输入/输出缓冲；
 *
 * @param filename - 文件名
 * @param mode     - 以什么模式打开，比如 "r", "rb", "r+"等
 * @return int     - 在成功时返回一个非空的FILE *指针，失败时返回NULL值；
 */
FILE *file_stdio::file_stdio_fopen(const char *filename, const char *mode) {
    return fopen(filename, mode);
}

/**
 * fread用于从一个文件流里读取数据；数据从文件流stream读到由ptr指向的数据缓冲区里；
 * fread和fwrite都是对数据记录进行操作，size参数指定<每个数据记录>的长度，计数器nitems给出要<传输的记录个数>；
 * 它的返回值是成功读到数据缓冲区里的记录个数(而不是字节数)；当到达文件尾部的时候，它的返回值可能会小于nitems，甚至可以是零；
 *
 * @param ptr    - 数据缓冲区
 * @param size   - 每个记录的数据长度
 * @param nitems - 所有数据记录的个数
 * @param stream - 输入文件流
 * @return int   - 它的返回值是成功读到数据缓冲区里的记录个数(而不是字节数)；当到达文件尾部的时候，它的返回值可能会小于nitems，甚至可以是零；
 */
size_t file_stdio::file_stdio_fread(void *ptr, size_t size, size_t nitems, FILE *stream) {
    return fread(ptr, size, nitems, stream);
}

/**
 * fwrite与fread有相似接口；它从指定的数据缓冲区里取出数据记录，并把它们写到输出流中；
 * 它的返回值是成功写入的记录的个数；
 *
 * @param ptr    - 数据缓冲区
 * @param size   - 每个数据记录的长度
 * @param nitems - 所有数据记录的个数
 * @param stream - 输出文件流
 * @return int   - 它的返回值是成功写入的记录的个数
 */
size_t file_stdio::file_stdio_fwrite(void *ptr, size_t size, size_t nitems, FILE *stream) {
    return fwrite(ptr, size, nitems, stream);
}

/**
 * 关闭指定的文件流stream，使得所有尚未写出的数据都写出；
 * 因为stdio库会对数据进行缓冲，所以使用fclose是很重要而且很有必要的；
 *
 * @param stream - 要准备关闭的指定文件流
 * @return int   - 关闭是否成功
 */
int file_stdio::file_stdio_fclose(FILE *stream) {
    return fclose(stream);
}

/**
 * 把文件流里的多有未写出的数据立刻写出；
 * 你可以使用这个函数来确保在试图读入一个用户响应之前，先向终端送出一个交互提示符；
 * 注意：调用fclose时，隐含了一次fflush操作，所以你不必在fclose之前调用fflush；
 *
 * @param stream - 要立刻写出的文件流
 * @return int   - 立刻写出是否成功
 */
int file_stdio::file_stdio_fflush(FILE *stream) {
    return fflush(stream);
}

/**
 * fseek函数是与lseek系统调用对应的文件流函数；它在文件流里为下一次读写操作指定位置；
 * offset和whence参数的含义和取值，与前面的lseek系统调用完全一样；但是lseek返回的是一个off_t数值，而fseek返回的是
 * 一个整数：0-表示成功，-1表示失败并设置errno指出错误；
 *
 * @param stream - 要seek的文件流
 * @param offset - 文件流指针位置
 * @param whence - whence参数用来定义该偏移值offset得用法
 * @return int   - 0-表示成功，-1表示失败并设置errno指出错误
 */
int file_stdio::file_stdio_fseek(FILE *stream, long offset, int whence) {
    return fseek(stream, offset, whence);
}

/**
 * fgetc函数从文件流里取出下一个字节并把它作为一个字符返回；当它到达文件尾部或出现错误时，它返回EOF；
 * 你必须通过ferror或feof来区分这两种情况；当它到达文件尾部或出现错误时，它返回EOF；
 *
 * @param stream - 要操作的文件流
 * @return int   - 返回取到的字符，当它到达文件尾部或出现错误时，它返回EOF；
 */
int file_stdio::file_stdio_fgetc(FILE *stream) {
    return fgetc(stream);
}

/**
 * getc函数和fgetc一样，但它有可能被实现为一个宏，如果是这样，stream参数就可能被计算不止一次，所以它不能有副作用；
 *
 *
 * @param stream - 要操作的文件流
 * @return int   - 返回取到的字符，当它到达文件尾部或出现错误时，它返回EOF；
 */
int file_stdio::file_stdio_getc(FILE *stream) {
    return getc(stream);
}

/**
 * getchar的作用与getc完全一样，它从标准输入里读取下一个字符；
 *
 * @return int - 返回取到的字符，当它到达文件尾部或出现错误时，它返回EOF；
 */
int file_stdio::file_stdio_getchar() {
    return getchar();
}

/**
 * fputc函数把一个字符写到一个输出文件流中；它返回写入的值；如果失败，返回EOF；
 *
 * @param c      - 要写入的字符
 * @param stream - 输出文件流
 * @return int   - 返回写入的值
 */
int file_stdio::file_stdio_fputc(int c, FILE *stream) {
    return fputc(c, stream);
}

/**
 * 同fputc
 *
 * @param c      - 要写入的字符
 * @param stream - 输出文件流
 * @return int   - 返回写入的值
 */
int file_stdio::file_stdio_putc(int c, FILE *stream) {
    return putc(c, stream);
}

/**
 * 同putc
 *
 * @param c      - 要写入的字符
 * @param stream - 输出文件流
 * @return int   - 返回写入的值
 */
int file_stdio::file_stdio_putchar(int c) {
    return putchar(c);
}

/**
 * 从输入文件流中，读取一个字符串，将从stream中读取的字符串写入s地址
 *
 * @param s      - 保存读取的字符串的地址
 * @param n      - 读取n个
 * @param stream - 输入文件流
 * @return char* - 成功返回指向字符串s的指针，到达文件结尾返回空指针，并且设置EOF，失败返回空指针，设置errno
 */
char *file_stdio::file_stdio_fgets(char *s, int n, FILE *stream) {
    return fgets(s, n, stream);
}

/**
 * 同fgets
 *
 * @param s      - 保存读取的字符串的指针
 * @return char* - 成功返回指向字符串s的指针，到达文件结尾返回空指针，并且设置EOF，失败返回空指针，设置errno
 */
char *file_stdio::file_stdio_gets(char *s) {
    /*gets弃用了*/
    return nullptr;
}

int file_stdio::file_stdio_printf(const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = printf(format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_sprintf(char *s, const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = sprintf(s, format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_fprintf(FILE *stream, const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = fprintf(stream, format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_scanf(const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = scanf(format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_fscanf(FILE *stream, const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = fscanf(stream, format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_sscanf(char *s, const char *format, ...) {
    va_list args;
    va_start(args, format);
    int result = sscanf(s, format, args);
    va_end(args);
    return result;
}

int file_stdio::file_stdio_ferror(FILE *stream) {
    return ferror(stream);
}

int file_stdio::file_stdio_feof(FILE *stream) {
    return feof(stream);
}

void file_stdio::file_stdio_clearerr(FILE *stream) {
    clearerr(stream);
}

int file_stdio::file_stdio_fileno(FILE *stream) {
    return fileno(stream);
}

FILE *file_stdio::file_stdio_fdopen(int fildes, const char *mode) {
    return fdopen(fildes, mode);
}

int file_stdio_main() {
    return 0;
}
